#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "idea.h"
#include "ckdes.h"

U8 dstbuf[1024]= {0};

extern int lz4_decompress(U8 *src, U8 *dst, int srcSize, int outputSize);

void printData1(char *title, U8 *data, int len)
{
	int i;

	printf("----------------------%s-----[%d]--------\n", title, len);
	for (i = 0; i < len; i++) {
		printf("0x%02x, ", (unsigned char)data[i]);
		if((i%16) == 15) printf("\n");
	}
	printf("\n");
}

void idea_en(IDEA_KEY_SCHEDULE *dkey, U8 *encdata, int enc_len, U8 *out, int *out_len)
{
	int i, n;

	n = (enc_len%8) ? ((enc_len/8)+1) : (enc_len/8);

	for(i = 0; i < n; i++) {
		idea_ecb_encrypt(encdata, out, dkey);
		encdata += 8;
		out += 8;
	}

	*out_len = enc_len;
}

int decrypt(long key, char *cipher, int cipher_len, char *msg, int *msg_len)
{
	int len, dstlen;
	IDEA_KEY_SCHEDULE *dkey = (IDEA_KEY_SCHEDULE *)key;

	if (cipher[0] == 0x30) {
		idea_en(dkey, cipher+1, cipher_len-1, msg, msg_len);
		
		len = *msg_len;
	} else {
		dstlen = *((U16 *)cipher+1);
		
		idea_en(dkey, cipher+4, cipher_len-4, (U8 *)dstbuf, msg_len);
		
		len = lz4_decompress(dstbuf, msg, HTONS(dstlen), 32767);
	}
	
	if (len > 0) {
		*msg_len = len;
		return 0;
	} else {
		printf("lz4_decompress error\n");
		return -1;
	}
}

int gen_passkey(char *passwd, char *keyout, char *userid, int inbufmaxlen)
{
	int i, j, n;
	char *temp, *temp1;
	char key[] = "MATRIXII";

	struct _desInst d1 = {0};

	char block[200] = {0};

	desinit(&d1);
	dessetkey(&d1, key);

	memcpy(block, passwd, 8);
	block[8] = '|';
	memset(block+9, 0x20, 11);

	n = (inbufmaxlen + 7) / 8;
	temp = block;
	temp1 = keyout;

	for (i = 0; i < n; i++) {
		endes(&d1, temp);

		for (j = 0; j < 8; j++) {
			sprintf(temp1, "%02x", (U8)*temp); 
			temp1 += 2;
			temp++;
		}
	}

	keyout[2*inbufmaxlen] = 0;
	printData1("keyout", (U8 *)keyout, 64);

	return 0;
}

long init_key(char *passwd, int passwd_len, char *datakey, int datakey_len)
{
	int datakey_msg_len;
	int datakey_msg[16] = {0};
	int passkey[16] = {0};
	
	IDEA_KEY_SCHEDULE key, dkey;
	IDEA_KEY_SCHEDULE *dcekey;

	printData1("passwd", passwd, passwd_len);
	printData1("datakey", datakey, datakey_len);
	
	dcekey = (IDEA_KEY_SCHEDULE *)malloc(sizeof(IDEA_KEY_SCHEDULE));
	if (!dcekey)  return 0;
	
	gen_passkey(passwd, (char *)passkey, "", 20);

	idea_set_encrypt_key((U8 *)passkey, &key);
	idea_set_decrypt_key(&key, &dkey);

	datakey_msg_len = sizeof(datakey_msg);
	idea_en(&dkey, datakey+1, datakey_len-1, (U8 *)datakey_msg, &datakey_msg_len);

	idea_set_encrypt_key((U8 *)datakey_msg, &key);
	idea_set_decrypt_key(&key, dcekey);
	
	printData1("key", (U8 *)&key, sizeof(key));
	printData1("dkey", (U8 *)&dkey, sizeof(dkey));

	return (long)dcekey;
}

